﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using XPressify.Core;
using XPressify.Data;
using XPressify.Data.Helpers;
using XPressify.Helpers;
using XPressify.Models;
using NotificationType = XPressify.Models.NotificationType;

namespace XPressify.Controllers
{
    public class ProfileController : SubjectController
    {
        [Authorize]
        public ActionResult ProfileView(Guid id, Guid? postId)
        {
            var viewerUser = CurrentUser;
            User ownerUser = id == Guid.Empty ? viewerUser : Repository.AsQueryable<User>().SingleOrDefault(us => us.Id == id);
            
            
            var isOwner = ownerUser.Id == viewerUser.Id;
            var areFriend = Repository.GetFriendsOf(ownerUser.Id).Any(usr => usr.Id == viewerUser.Id);
            var anyFriendRelationshipExist = Repository.AsQueryable<Relationship>().Any(
                rel =>
                ((rel.BaseSubject.Id == ownerUser.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                (rel.BaseSubject.Id == viewerUser.Id && rel.BaseSubject2.Id == ownerUser.Id)) &&
                rel.RelationType == RelationshipType.FriendOf);

            //if owner requested friendship to viewer then we will create button accept as friend
            var ownerRequestedFriendshipToViewerRel = Repository.AsQueryable<Relationship>().SingleOrDefault(
                rel => rel.BaseSubject.Id == ownerUser.Id && rel.BaseSubject2.Id == viewerUser.Id &&
                       rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Requested);
            var ownerRequestedFriendshipToViewerExist = false;
            if(ownerRequestedFriendshipToViewerRel != null)
            {
                //request exist
                ownerRequestedFriendshipToViewerExist = true;
            }

            var profileAlbumId =
                Repository.AsQueryable<Album>().SingleOrDefault(al => al.BaseSubject.Id == ownerUser.Id && al.IsProfile);
            var profilePicture = profileAlbumId.Medias.SingleOrDefault(pr => pr.IsProfile);
            var ownerProfilePicturePath = "/Media/" + profilePicture.BaseSubject.Id + "/" + profilePicture.Album.Id + "/" + "ProfilePicture";
            
            var relationshipWithHimSelf = false;
            var relationshipExist = false;
            var previousRelationship = Repository.AsQueryable<Relationship>().SingleOrDefault(
                rel =>
                (rel.BaseSubject.Id == ownerUser.Id || rel.BaseSubject2.Id == ownerUser.Id) &&
                (rel.RelationType == RelationshipType.InRelationshipWith ||
                 rel.RelationType == RelationshipType.ItsComplicatedWith ||
                 rel.RelationType == RelationshipType.MarriedWith ||
                 rel.RelationType == RelationshipType.EngagedWith || 
                 rel.RelationType == RelationshipType.OpenRelationshipWith ||
                 rel.RelationType == RelationshipType.IsSingle || 
                 rel.RelationType == RelationshipType.IsWidowed ||
                 rel.RelationType == RelationshipType.IsDivorced) &&
                rel.Status == RelationshipStatus.Confirmed); // find an id of previous relationship user
            User previousRelationshipUser = null;
            var relationshipType = "";
            if (previousRelationship != null)
            {
                if(previousRelationship.BaseSubject.Id == ownerUser.Id)
                {
                    previousRelationshipUser = (User)previousRelationship.BaseSubject2;
                }
                else if (previousRelationship.BaseSubject2.Id == ownerUser.Id)
                {
                    previousRelationshipUser = (User)previousRelationship.BaseSubject;
                }
                if(previousRelationship.BaseSubject.Id == previousRelationship.BaseSubject2.Id) // relationship with him self
                {
                    relationshipWithHimSelf = true;
                }
                relationshipType = GetLoveRelationTypeName(previousRelationship);
            }

            //get all posts from owner user and put them in dictionary
            var dictionary = new Dictionary<Post, List<Post>>();

            //selected only one post
            var choosedPost =
                Repository.AsQueryable<Post>().SingleOrDefault(p => p.Id == postId && p.PostType == PostType.Post);
            var areFriendsOfFriends = true;
            var areFriends = true;
            if(!isOwner)
            {
                areFriendsOfFriends = Repository.GetFriendsOfFriendsOf(viewerUser.Id).Any(fr => fr.Id == ownerUser.Id); 
                areFriends = Repository.GetFriendsOf(viewerUser.Id).Any(fr => fr.Id == ownerUser.Id);
            }
            
            if(choosedPost != null)
            {
                if ((choosedPost.BaseObject.PrivacyType == ObjectPrivacy.Everyone ||
                    (choosedPost.BaseObject.PrivacyType == ObjectPrivacy.FriendsOnly && areFriends) ||
                    (choosedPost.BaseObject.PrivacyType == ObjectPrivacy.FriendsOfFriends && (areFriendsOfFriends || areFriends))) || isOwner)
                {
                    var allComment = Repository.GetAllComments(choosedPost);
                    dictionary.Add(choosedPost, allComment);
                }
                
            }
            else
            {
                var allPosts =
                Repository.AsQueryable<Post>().Where(
                    pst => pst.BaseSubject.Id == ownerUser.Id && pst.PostType == PostType.Post).OrderByDescending(st => st.Created);
                foreach (var post in allPosts)
                {
                    if((post.BaseObject.PrivacyType == ObjectPrivacy.Everyone || 
                    (post.BaseObject.PrivacyType == ObjectPrivacy.FriendsOnly && areFriends) ||
                    (post.BaseObject.PrivacyType == ObjectPrivacy.FriendsOfFriends && (areFriendsOfFriends || areFriends))) || isOwner)
                    {
                        var allComments = Repository.GetAllComments(post);
                        dictionary.Add(post, allComments);
                    }
                }
            }
            

            var isBlocked = // check if its blocked
                Repository.AsQueryable<Relationship>().Any(
                    rel =>
                    ((rel.BaseSubject.Id == ownerUser.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                    (rel.BaseSubject2.Id == ownerUser.Id && rel.BaseSubject.Id == viewerUser.Id)) &&
                    rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked);
            var wallAlbumId =
                Repository.AsQueryable<Album>().SingleOrDefault(al => al.BaseSubject.Id == ownerUser.Id && al.IsWall).Id;

            var isAjaxRequest = Request.IsAjaxRequest() ? true : false;
            

            var model = new ProfileViewModel
                            {
                                IsOwner = isOwner,
                                ProfileAlbumId = profileAlbumId.Id,
                                OwnerProfilePicturePath = ownerProfilePicturePath,
                                OwnerUser = ownerUser,
                                ViewerUserId = viewerUser.Id,
                                IsFriend = areFriend,
                                LoveRelationshipWithHimself = relationshipWithHimSelf,
                                previousLoveRelationshipUser = previousRelationshipUser,
                                LoveRelationshipType = relationshipType,
                                IsBlocked = isBlocked,
                                WallAlbumId = wallAlbumId,
                                Posts = dictionary,
                                AnyFriendRelationship = anyFriendRelationshipExist, // any relationship with status postopned,confirmed,blocked or requsted
                                ViewerProfilePicturePath = Repository.GetProfilePicturePath(viewerUser.Id),
                                OwnerRequestedFriendshipExist = ownerRequestedFriendshipToViewerExist,
                                OwnerRequestedFriendshipRel = ownerRequestedFriendshipToViewerRel,
                                IsAjaxRequest = isAjaxRequest
                            };

            return View(model);
        } 

        public ActionResult ProfileInfo(Guid id)
        {
            var viewerUser = CurrentUser;
            User ownerUser = id == Guid.Empty ? viewerUser : Repository.AsQueryable<User>().SingleOrDefault(us => us.Id == id);
            var isOwner = ownerUser.Id == viewerUser.Id;
            var areFriends = isOwner;
            if(!areFriends)
            {
                areFriends = Repository.GetFriendsOf(ownerUser.Id).Any(usr => usr.Id == viewerUser.Id);
            }


            //if profile is private and they are not friends it will not show
            var privateProfile = (areFriends || isOwner ||
                                       (!areFriends && ownerUser.PrivacyType == SubjectPrivacy.Public))
                                          ? false
                                         : true;
            //if blocked it will not show
            var isBlocked = false;
            if(!areFriends)
            {
                isBlocked = // check if its blocked
                Repository.AsQueryable<Relationship>().Any(
                    rel =>
                    ((rel.BaseSubject.Id == ownerUser.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                    (rel.BaseSubject2.Id == ownerUser.Id && rel.BaseSubject.Id == viewerUser.Id)) &&
                    rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked);
            }



            var partnerDefined = false;
            var loveRelationship = Repository.AsQueryable<Relationship>().SingleOrDefault(
                rel =>
                (rel.BaseSubject.Id == ownerUser.Id || rel.BaseSubject2.Id == ownerUser.Id) &&
                (rel.RelationType == RelationshipType.InRelationshipWith ||
                 rel.RelationType == RelationshipType.ItsComplicatedWith ||
                 rel.RelationType == RelationshipType.MarriedWith ||
                 rel.RelationType == RelationshipType.EngagedWith ||
                 rel.RelationType == RelationshipType.OpenRelationshipWith ||
                 rel.RelationType == RelationshipType.IsSingle ||
                 rel.RelationType == RelationshipType.IsWidowed ||
                 rel.RelationType == RelationshipType.IsDivorced) &&
                rel.Status == RelationshipStatus.Confirmed); // find an id of previous relationship user
            User loveRelationshipUser = null;
            var relationshipType = "";
            if (loveRelationship != null)
            {
                if (loveRelationship.BaseSubject.Id == ownerUser.Id)
                {
                    loveRelationshipUser = (User)loveRelationship.BaseSubject2;
                }
                else if (loveRelationship.BaseSubject2.Id == ownerUser.Id)
                {
                    loveRelationshipUser = (User)loveRelationship.BaseSubject;
                }
                if (loveRelationship.BaseSubject.Id != loveRelationship.BaseSubject2.Id) // relationship with him self
                {
                    partnerDefined = true;
                }
                relationshipType = GetLoveRelationTypeName(loveRelationship);
            }

            var allFamilyRelationships = GetAllFamilyRelationships(ownerUser);

            var model = new ProfileInfoModel()
                            {
                                AllRelationshipChild = allFamilyRelationships["Childrens"].ToArray(),
                                AllRelationshipParent = allFamilyRelationships["Parents"].ToArray(),
                                AllRelationshipSibling = allFamilyRelationships["Siblings"].ToArray(),
                                AllRelationshipCousin = allFamilyRelationships["Cousins"].ToArray(),
                                AllRelationshipGrandchild = allFamilyRelationships["Grandchildrens"].ToArray(),
                                AllRelationshipGrandparent = allFamilyRelationships["Grandparents"].ToArray(),
                                AllRelationshipNephewNiece = allFamilyRelationships["Nephews/Nieces"].ToArray(),
                                AllRelationshipUncleAunt = allFamilyRelationships["Uncles/Aunts"].ToArray(),
                                OwnerUser = ownerUser,
                                LoveRelationship = loveRelationship,
                                LoveRelationshipUser = loveRelationshipUser,
                                RelationshipType = relationshipType,
                                Show = (privateProfile || isBlocked) ? false : true,
                                IsOwner = isOwner
                            };
            return View(model);
        }

        //
        // GET: /Profile/Edit/5
        [Authorize]
        public ActionResult ProfileEdit()
        {
            var currentUser = CurrentUser;
            // find an id of previous relationship user // we dont look for status accepted so user can delete the request so he can make a new requests
            var previousRelationship = Repository.AsQueryable<Relationship>().SingleOrDefault(
                rel =>
                (rel.BaseSubject.Id == currentUser.Id || rel.BaseSubject2.Id == currentUser.Id) &&
                (rel.RelationType == RelationshipType.InRelationshipWith ||
                 rel.RelationType == RelationshipType.ItsComplicatedWith ||
                 rel.RelationType == RelationshipType.MarriedWith ||
                 rel.RelationType == RelationshipType.EngagedWith || 
                 rel.RelationType == RelationshipType.OpenRelationshipWith ||
                 rel.RelationType == RelationshipType.IsSingle || 
                 rel.RelationType == RelationshipType.IsWidowed ||
                 rel.RelationType == RelationshipType.IsDivorced));
            User previousRelationshipUser = null;
            var relationshipType = "";
            var previousRelationshipId = Guid.Empty;
            if (previousRelationship != null)
            {
                if (previousRelationship.BaseSubject.Id == currentUser.Id)
                {
                    previousRelationshipUser = (User)previousRelationship.BaseSubject2;
                    previousRelationshipId = previousRelationshipUser.Id;
                }
                else if (previousRelationship.BaseSubject2.Id == currentUser.Id)
                {
                    previousRelationshipUser = (User)previousRelationship.BaseSubject;
                    previousRelationshipId = previousRelationshipUser.Id;
                }
            }

            var model = new ProfileEditModel()
                            {
                                Birthday = currentUser.Birthday,
                                Email = currentUser.Email,
                                FirstName = currentUser.FirstName,
                                LastName = currentUser.LastName,
                                Gender = currentUser.Gender,
                                PrivacyType = currentUser.PrivacyType,
                                UserId = currentUser.Id,
                                Username = currentUser.Username,
                                PreviousLoveRelationshipId = previousRelationshipId,
                            };
            return View(model);
        }

        //
        // POST: /Profile/Edit/5
        [Authorize]
        [HttpPost]
        public ActionResult ProfileEdit(ProfileEditModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var valid = true;
                                                                                                    
                    // validate the model
                    if (Repository.AsQueryable<User>().Any(x => x.Id != model.UserId && x.Email == model.Email))
                    {
                        ModelState.AddModelError("Email", "Email already exists");
                        valid = false;
                    }   
                    if(valid)
                    {
                        var user = Repository.AsQueryable<User>().SingleOrDefault(usr => usr.Id == model.UserId);
                        user.Birthday = model.Birthday;
                        user.Email = model.Email;
                        user.FirstName = model.FirstName;
                        user.LastName = model.LastName;
                        user.Gender = model.Gender;
                        user.PrivacyType = model.PrivacyType;
                        user.Username = model.Username ?? "";
                        Repository.SaveChanges();
                        return RedirectToAction("ProfileView", new {id = user.Id});
                    }
                    
                }
                catch
                {
                    return View(model);
                }
            }
            return View(model);
        }

        [Authorize]
        public ActionResult RelationshipLoveEdit()
        {
            var user = CurrentUser;
            var anyPreviousRelationship = Repository.AsQueryable<Relationship>().Any(
                rel =>
                (rel.BaseSubject.Id == user.Id || rel.BaseSubject2.Id == user.Id) &&
                (rel.RelationType == RelationshipType.InRelationshipWith ||
                 rel.RelationType == RelationshipType.ItsComplicatedWith ||
                 rel.RelationType == RelationshipType.MarriedWith ||
                 rel.RelationType == RelationshipType.EngagedWith ||
                 rel.RelationType == RelationshipType.OpenRelationshipWith ||
                 rel.RelationType == RelationshipType.IsSingle ||
                 rel.RelationType == RelationshipType.IsWidowed ||
                 rel.RelationType == RelationshipType.IsDivorced) && rel.Status != RelationshipStatus.Blocked);

             var allFriends = Repository.GetFriendsOf(user.Id);
             var friendsLookupList = new List<FriendsLookupModels>();
             foreach (var friend in allFriends)
             {
                 var newMember = new FriendsLookupModels()
                 {
                     FirstName = friend.FirstName,
                     Fullname = friend.FullName,
                     LastName = friend.LastName,
                     Id = friend.Id,
                     ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                     Selected = false
                 };
                 friendsLookupList.Add(newMember);
             }
             var json = JsonHelper.Serialize(friendsLookupList);
             Session["allFriends"] = json;

            var model = new RelationshipLoveEditModel()
            {
                AnyPreviousRelationship = anyPreviousRelationship,
                CurrentUserId = user.Id
            };
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult RelationshipLoveEdit(RelationshipLoveEditModel theModel)
        {
            var user = CurrentUser;
            var selectedUser = Repository.AsQueryable<User>().SingleOrDefault(u => u.Id == theModel.SelectedUser);


            // if selected divorced, single or widowed then we set selectedUser to null cause those are single relationships
            if(theModel.RelationshipType == RelationshipType.IsDivorced || 
                theModel.RelationshipType == RelationshipType.IsSingle || 
                theModel.RelationshipType == RelationshipType.IsWidowed)
            {
                selectedUser = null;
            }

            //Create default relationship for not choosed user
            var relationship = new Relationship()
            {
                BaseSubject = user,
                BaseSubject2 = user,
                Created = DateTime.Now,
                PrivacyType = ObjectPrivacy.FriendsOnly,
                RelationType = theModel.RelationshipType,
                Status = RelationshipStatus.Confirmed,
                Type = ObjectType.Relationship,
                Id = Guid.NewGuid(),
                Description = "Love relationship",
                Name = "Love relationship"
            };

            if(selectedUser == null)
            {
                
                Repository.AddObject(relationship);

                //create RelationshipStatusChange post
                var newPost = new Post()
                {
                    BaseObject = relationship,
                    BaseSubject = user,
                    Created = relationship.Created,
                    Description = "Love relationship post",
                    PostType = PostType.Post,
                    Type = BaseMessageType.Post,
                    Title = "Love relationship post",
                    Id = Guid.NewGuid(),
                    CommentType = CommentType.PostWithItsComments
                };

                var viewData = new
                {
                    YourId = user.Id,
                    YourFullname = user.FullName,
                    RelationshipType = GetLoveRelationTypeName(relationship),
                    ExistUser = "false",
                    FriendFullname = "",
                    FriendId = Guid.Empty,
                    Created = newPost.Created,
                    PostId = newPost.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(user.Id)
                };
                var viewDictionary = viewData.ToViewDataDictionary();
                newPost.Content = ControlToString("~/Views/Post/RelationshipStatusChange.cshtml", viewDictionary);
                Repository.AddObject(newPost);
                Repository.SaveChanges();
                return RedirectToAction("ProfileView", new { id = user.Id });
            }
            else
            {
                relationship.BaseSubject2 = selectedUser;
                relationship.Status = RelationshipStatus.Requested;

                //make RequstedRelationshipWithYou notification
                var newNotification = new Notification()
                {
                    Active = true,
                    BaseSubject = selectedUser,
                    Created = DateTime.Now,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Notification
                };
                var viewData2 = new
                {
                    UserId = user.Id,
                    UserFullname = user.FullName,
                    RelationshipType = "love"
                };
                var viewDictionary2 = viewData2.ToViewDataDictionary();
                newNotification.Content = ControlToString("~/Views/Notification/RequstedRelationshipWithYou.cshtml", viewDictionary2);
                Repository.AddObject(newNotification);

                Repository.SaveChanges();
                SendEmailConfirmRelationship(relationship);
                var notifyModel = new NotifyModel
                {
                    Title = "Relationship request sent",
                    Header = "Relationship request sent",
                    Body = "Relationship request was successfully send. You need to wait for confirmation to be accepted.",
                    NotificationType = NotificationType.Information
                };
                return RedirectToAction("Notify", "Home", notifyModel);
            }

        }
    

        [Authorize]
        public ActionResult RelationshipLoveDelete()
        {
            var user = CurrentUser;
            
            //we look for previous relationship // we dont look for status confirmed so user can delete requested status which is pending
            var previousLoveRelationship =
                Repository.AsQueryable<Relationship>().SingleOrDefault(
                    rel =>
                    (rel.BaseSubject.Id == CurrentUser.Id || rel.BaseSubject2.Id == CurrentUser.Id) &&
                    (rel.RelationType == RelationshipType.InRelationshipWith ||
                     rel.RelationType == RelationshipType.ItsComplicatedWith ||
                     rel.RelationType == RelationshipType.MarriedWith ||
                     rel.RelationType == RelationshipType.EngagedWith ||
                     rel.RelationType == RelationshipType.OpenRelationshipWith ||
                     rel.RelationType == RelationshipType.IsSingle ||
                     rel.RelationType == RelationshipType.IsWidowed ||
                     rel.RelationType == RelationshipType.IsDivorced) && rel.Status != RelationshipStatus.Blocked);
            var previousLoveRelationshipUser = previousLoveRelationship.BaseSubject.Id == user.Id
                                                   ? previousLoveRelationship.BaseSubject2
                                                   : previousLoveRelationship.BaseSubject;
            var profilePicturePath = Repository.GetProfilePicturePath(previousLoveRelationshipUser.Id);
            var relationshipUser = new Friend()
                                       {
                                           FullName = previousLoveRelationshipUser.FullName,
                                           Id = previousLoveRelationshipUser.Id,
                                           ProfilePicturePath = profilePicturePath
                                       };
            var model = new RelationshipLoveDeleteModel()
                            {
                                RelationshipUser = relationshipUser,
                                UserId = CurrentUser.Id,
                                RelationshipStatus = GetLoveRelationTypeName(previousLoveRelationship),
                                Relationship = previousLoveRelationship
                            };
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult RelationshipLoveDelete(RelationshipLoveDeleteModel model)
        {
            var user = CurrentUser;
            
            // relationship created from column BaseSubject // with no status confirmed so user can delete pending request so user can make another request
            var previousRelationship = 
                Repository.AsQueryable<Relationship>().SingleOrDefault(
                    rel =>
                    (rel.BaseSubject.Id == user.Id || rel.BaseSubject2.Id == user.Id) &&
                    (rel.RelationType == RelationshipType.InRelationshipWith ||
                     rel.RelationType == RelationshipType.ItsComplicatedWith ||
                     rel.RelationType == RelationshipType.MarriedWith ||
                     rel.RelationType == RelationshipType.EngagedWith ||
                     rel.RelationType == RelationshipType.OpenRelationshipWith ||
                     rel.RelationType == RelationshipType.IsSingle ||
                     rel.RelationType == RelationshipType.IsWidowed ||
                     rel.RelationType == RelationshipType.IsDivorced) && rel.Status != RelationshipStatus.Blocked);
            if(previousRelationship != null)
            {
                var users = new List<User>();
                users.Add(user);
                var existSecondUser = previousRelationship.BaseSubject.Id == previousRelationship.BaseSubject2.Id
                                          ? false
                                          : true;
                var secondUser = previousRelationship.BaseSubject.Id == user.Id
                                     ? (User)previousRelationship.BaseSubject2
                                     : (User)previousRelationship.BaseSubject;
                if(existSecondUser)
                {
                    users.Add(secondUser);
                }

                foreach (var user1 in users)
                {
                    //create RelationshipStatusDelete post
                    var newPost = new Post()
                    {
                        BaseObject = previousRelationship,
                        BaseSubject = user1,
                        Created = DateTime.Now,
                        Description = "Love relationship post",
                        PostType = PostType.Post,
                        Type = BaseMessageType.Post,
                        Title = "Love relationship post",
                        Id = Guid.NewGuid(),
                        CommentType = CommentType.PostWithItsComments
                    };
                    var viewData = new
                    {
                        YourId = user1.Id,
                        YourFullname = user1.FullName,
                        RelationshipType = GetLoveRelationTypeName(previousRelationship),
                        Created = newPost.Created,
                        PostId = newPost.Id,
                        ProfilePicturePath = Repository.GetProfilePicturePath(user1.Id)
                    };
                    var viewDictionary = viewData.ToViewDataDictionary();
                    newPost.Content = ControlToString("~/Views/Post/RelationshipStatusDelete.cshtml", viewDictionary);
                    Repository.AddObject(newPost);
                    
                }
                Repository.SaveChanges();
                

                //if exist some post that are connected with this relationship then we dont delete the rel we just make it blocked
//                if(Repository.AsQueryable<Post>().Any(pst => pst.BaseObject.Id == previousRelationship.Id && pst.Type == PostType.Post))
                previousRelationship.Status = RelationshipStatus.Blocked; // this means its removed but not delete cause of the post that is connected with it
//                else
//                {
//                    Repository.DeleteObject(previousRelationship);
//                }
                Repository.SaveChanges();
            }
            
            return Json(model);
        }

        [Authorize]
        public ActionResult RelationshipFamilyEdit()
        {
            var user = CurrentUser;
            var allFriends = Repository.GetFriendsOf(user.Id);
            var friendsLookupList = new List<FriendsLookupModels>();
            foreach (var friend in allFriends)
            {
                var newMember = new FriendsLookupModels()
                {
                    FirstName = friend.FirstName,
                    Fullname = friend.FullName,
                    LastName = friend.LastName,
                    Id = friend.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                    Selected = false
                };
                friendsLookupList.Add(newMember);
            }
            var json = JsonHelper.Serialize(friendsLookupList);
            Session["allFriends"] = json;

            var model = new RelationshipFamilyEditModel()
            {
                CurrentUserId = CurrentUser.Id
            };
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult RelationshipFamilyEdit(RelationshipFamilyEditModel model)
        {
            var user = CurrentUser;
            if (ModelState.IsValid)
            {
                if(model.SelectedUser != Guid.Empty)
                {
                    var selectedFriend = Repository.AsQueryable<User>().SingleOrDefault(usr => usr.Id == model.SelectedUser);
                    var newRelationship = new Relationship()
                    {
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        PrivacyType = ObjectPrivacy.FriendsOnly,
                        Status = RelationshipStatus.Requested,
                        Type = ObjectType.Relationship,
                        Description = "Family relationship",
                        Name = user.Id.ToString()            // it uses for finding out who requested relationship// Using in functions postponeList, requestedList & blockedList
                    };
                    var Opposite = false;
                    // if its true then we will put current user in BaseSubject2 column in relationship
                    int relationshipType = 0;
                    // this will be real relatinship type // in model it will exist -1, -2 , -3 which means oppposite of 1,2,3 which are child, grandchild or siblingchild (opposite: parent, grandparent, uncle/aunt)
                    if (model.RelationType == (RelationshipType.ChildOf * -1) || model.RelationType == (RelationshipType.GrandchildOf * -1) || model.RelationType == (RelationshipType.SiblingchildOf * -1)) // for selected parent, grandParent or uncle/aunt
                    {
                        relationshipType = model.RelationType * (-1);
                        // we make it to positive integer // eg. "currentUser" is child of X  which means X is parent of currentUser
                    }
                    else if (model.RelationType == RelationshipType.ChildOf || model.RelationType == RelationshipType.GrandchildOf || model.RelationType == RelationshipType.SiblingchildOf)
                    {
                        Opposite = true;
                        relationshipType = model.RelationType;
                        // current user will be put in BaseSubject2 column // for childOf, grandchildOf, siblingchildOf //eg. X is child of "currentUser"
                    }
                    if (Opposite) // if opposite then we need to put currentUser to BaseSubject2 column
                    {
                        newRelationship.BaseSubject = selectedFriend;
                        newRelationship.BaseSubject2 = user;
                        newRelationship.RelationType = (short)relationshipType;
                    }
                    else // we need to put currentUser to BaseSubject2 column
                    {
                        newRelationship.BaseSubject = user;
                        newRelationship.BaseSubject2 = selectedFriend;
                        newRelationship.RelationType = (short)relationshipType;
                    }
                    Repository.AddObject(newRelationship);

                    //make RequstedRelationshipWithYou notification
                    var newNotification = new Notification()
                    {
                        Active = true,
                        BaseSubject = selectedFriend,
                        Created = DateTime.Now,
                        Id = Guid.NewGuid(),
                        Type = BaseMessageType.Notification
                    };
                    var viewData2 = new
                    {
                        UserId = user.Id,
                        UserFullname = user.FullName,
                        RelationshipType = "family"
                    };
                    var viewDictionary2 = viewData2.ToViewDataDictionary();
                    newNotification.Content = ControlToString("~/Views/Notification/RequstedRelationshipWithYou.cshtml", viewDictionary2);
                    Repository.AddObject(newNotification);

                    Repository.SaveChanges();

                    SendEmailConfirmRelationship(newRelationship);
                    return RedirectToAction("ProfileView", "Profile", new { id = user.Id });
                }
                
            }
            return View(model);
            
        }

        [Authorize]
        public ActionResult RelationshipFamilyDelete(Guid id)
        {
            var user = CurrentUser;
            var allRelationship = // find all family relationships with current user
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject.Id == user.Id &&
                     (rel.RelationType == RelationshipType.ChildOf ||
                      rel.RelationType == RelationshipType.SiblingOf ||
                      rel.RelationType == RelationshipType.CousinOf ||
                      rel.RelationType == RelationshipType.SiblingchildOf ||
                      rel.RelationType == RelationshipType.GrandchildOf))).Union(Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject2.Id == user.Id &&
                     (rel.RelationType == RelationshipType.ChildOf ||
                      rel.RelationType == RelationshipType.CousinOf ||
                      rel.RelationType == RelationshipType.SiblingchildOf ||
                      rel.RelationType == RelationshipType.SiblingOf ||
                      rel.RelationType == RelationshipType.GrandchildOf))));

            allRelationship.OrderBy(rel => rel.RelationType); // order by relationship type
            var allFamilyRelationshipUser = new List<Friend>(); // all family relationship users
            foreach (var relationship in allRelationship)
            {
                var newFriend = new Friend()
                                    {
                                        IsSelected = false,
                                        RelationshipId = relationship.Id
                                    };
                if(relationship.BaseSubject.Id == user.Id)
                {
                    newFriend.Id = relationship.BaseSubject2.Id;
                    newFriend.FullName = relationship.BaseSubject2.FullName;
                }
                else
                {
                    newFriend.Id = relationship.BaseSubject.Id;
                    newFriend.FullName = relationship.BaseSubject.FullName;
                }


                var friendProfilePicturePath = Repository.GetProfilePicturePath(newFriend.Id);

                newFriend.ProfilePicturePath = friendProfilePicturePath;
                newFriend.RelationshipType = GetLoveRelationTypeName(relationship);
                allFamilyRelationshipUser.Add(newFriend);
            }
            var model = new RelationshipFamilyDeleteModel()
                            {
                                AllFamilyUsers = allFamilyRelationshipUser.ToArray(),
                                CurrentUserId = user.Id
                            };
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult RelationshipFamilyDelete(Guid id, RelationshipFamilyDeleteModel model)
        {
            var user = CurrentUser;
            if(model.AllFamilyUsers != null)
            {
                foreach (var familyRelationshipUser in model.AllFamilyUsers)
                {
                    if (familyRelationshipUser.IsSelected)
                    {
                        var relationship =
                            Repository.AsQueryable<Relationship>().SingleOrDefault(
                                rel => rel.Id == familyRelationshipUser.RelationshipId);
                        Repository.DeleteObject(relationship);
                    }
                }
                Repository.SaveChanges();
            }
            return Json(model);
        }

        [Authorize]
        public ActionResult FriendList(Guid id, int? page)
        {
            var viewerUser = CurrentUser;
            var ownerId = id;
            if(ownerId == Guid.Empty)
            {
                ownerId = viewerUser.Id;
            }

            
            if (id == Guid.Empty) // if its empty then its own friends list
                ownerId = viewerUser.Id;
            var blockedFriends =                            // all users that are blocked
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject.Id == viewerUser.Id || rel.BaseSubject2.Id == viewerUser.Id) &&
                    rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked);


            var friends = Repository.GetFriendsOf(ownerId).Where(
                    usr => !(blockedFriends.Any(bl => bl.BaseSubject.Id == usr.Id || bl.BaseSubject2.Id == usr.Id)));
//                Repository.GetFriendsOf(ownerId).Where(
//                    usr => !(blockedFriends.Any(bl => bl.BaseSubject.Id == usr.Id || bl.BaseSubject2.Id == usr.Id)));

            //Session friends
            var friendsLookupList = new List<FriendsLookupModels>();
            foreach (var friend in friends)
            {
                var newMember = new FriendsLookupModels()
                {
                    FirstName = friend.FirstName,
                    Fullname = friend.FullName,
                    LastName = friend.LastName,
                    Id = friend.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                    Selected = false
                };
                friendsLookupList.Add(newMember);
            }
            var json = JsonHelper.Serialize(friendsLookupList);
            Session["allFriends" + ownerId] = json;

            var addFriend = false; // if true it will show add as a friend button next to the user
            var confirmFriend = false; // if true it will show confirm friendship button next to the user
            var friendsList = new List<Friend>();
            var friendsPageable = friends.GetPageable(page ?? 1, 50, (g => g.Created));
            foreach (var friend in friendsPageable.Page)
            {
                addFriend = false;
                confirmFriend = false;
                var friendProfilePicturePath = Repository.GetProfilePicturePath(friend.Id);
                addFriend =
                    !Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (((rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                         (rel.BaseSubject2.Id == friend.Id && rel.BaseSubject.Id == viewerUser.Id)) &&
                        rel.RelationType == RelationshipType.FriendOf)); // try to find if there is any of relationship with current user if so then we will not show button addFriend
                if (friend.Id == viewerUser.Id) // if friend is viewer user then we dont show addFriend button
                    addFriend = false;
                confirmFriend =
                    Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) &&
                        rel.RelationType == RelationshipType.FriendOf &&
                        (rel.Status == RelationshipStatus.Requested || rel.Status == RelationshipStatus.Postponed)); // friend (requested or gotpostopend by) current user then we show confirm friendship button

                var friendModel = new Friend()
                {
                    FullName = friend.FullName,
                    Id = friend.Id,
                    ProfilePicturePath = friendProfilePicturePath,
                    AddFriend = addFriend,
                    ConfirmFriend = confirmFriend
                };
                friendsList.Add(friendModel);
            }
            bool isOwner = ownerId == viewerUser.Id;
            var model = new ProfileFriendListModel()
                            {
                                AllFriends = friendsList.ToArray(),
                                OwnerUserId = ownerId,
                                IsOwner = isOwner,
                                Page = friendsList,
                                PageCount = friendsPageable.PageCount,
                                PageIndex = friendsPageable.PageIndex,
                                Id = id
                            };

            return View(model);
        }

        [Authorize]
        public ActionResult FriendListPopup(Guid id)
        {
            var viewerUser = CurrentUser;
            var ownerId = id;
            if (id == Guid.Empty) // if its empty then its own friends list
                ownerId = viewerUser.Id;
            var blockedFriends =                            // all users that are blocked
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject.Id == viewerUser.Id || rel.BaseSubject2.Id == viewerUser.Id) &&
                    rel.RelationType == RelationshipType.FriendOf && rel.Status == RelationshipStatus.Blocked);
            var friends = Repository.GetFriendsOf(ownerId).Where(
                    usr => !(blockedFriends.Any(bl => bl.BaseSubject.Id == usr.Id || bl.BaseSubject2.Id == usr.Id)));
//                Repository.GetFriendsOf(ownerId).Where(
//                    usr => !(blockedFriends.Any(bl => bl.BaseSubject.Id == usr.Id || bl.BaseSubject2.Id == usr.Id)));

            //Session friends
            var friendsLookupList = new List<FriendsLookupModels>();
            foreach (var friend in friends)
            {
                var newMember = new FriendsLookupModels()
                {
                    FirstName = friend.FirstName,
                    Fullname = friend.FullName,
                    LastName = friend.LastName,
                    Id = friend.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                    Selected = false
                };
                friendsLookupList.Add(newMember);
            }
            var json = JsonHelper.Serialize(friendsLookupList);
            Session["allFriends" + ownerId] = json;

            var addFriend = false; // if true it will show add as a friend button next to the user
            var confirmFriend = false; // if true it will show confirm friendship button next to the user
            var friendsList = new List<Friend>();
            foreach (var friend in friends)
            {
                addFriend = false;
                confirmFriend = false;
                var friendProfilePicturePath = Repository.GetProfilePicturePath(friend.Id);
                addFriend =
                    !Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (((rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                         (rel.BaseSubject2.Id == friend.Id && rel.BaseSubject.Id == viewerUser.Id)) &&
                        rel.RelationType == RelationshipType.FriendOf)); // try to find if there is any of relationship with current user if so then we will not show button addFriend
                if (friend.Id == viewerUser.Id) // if friend is viewer user then we dont show addFriend button
                    addFriend = false;
                confirmFriend =
                    Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) &&
                        rel.RelationType == RelationshipType.FriendOf &&
                        (rel.Status == RelationshipStatus.Requested || rel.Status == RelationshipStatus.Postponed)); // friend (requested or gotpostopend by) current user then we show confirm friendship button

                var friendModel = new Friend()
                {
                    FullName = friend.FullName,
                    Id = friend.Id,
                    ProfilePicturePath = friendProfilePicturePath,
                    AddFriend = addFriend,
                    ConfirmFriend = confirmFriend
                };
                friendsList.Add(friendModel);
            }
            bool isOwner = ownerId == viewerUser.Id;
            var model = new ProfileFriendListModel()
            {
                AllFriends = friendsList.ToArray(),
                OwnerUserId = ownerId,
                IsOwner = isOwner,
                Id = id
//                Page = friendsList,
//                PageCount = friendsPageable.PageCount,
//                PageIndex = friendsPageable.PageIndex
            };

            return PartialView(model);
        }

        [Authorize]
        public ActionResult FriendListDelete(Guid id)
        {
            var viewerUser = CurrentUser;
            var allFriends = Repository.GetFriendsOf(viewerUser.Id);
            var friendsLookupList = new List<FriendsLookupModels>();
            foreach (var friend in allFriends)
            {
                var newMember = new FriendsLookupModels()
                {
                    FirstName = friend.FirstName,
                    Fullname = friend.FullName,
                    LastName = friend.LastName,
                    Id = friend.Id,
                    ProfilePicturePath = Repository.GetProfilePicturePath(friend.Id),
                    Selected = false
                };
                friendsLookupList.Add(newMember);
            }
            var json = JsonHelper.Serialize(friendsLookupList);
            Session["allFriends"] = json;

            var model = new FriendListDeleteModel()
            {
                CurrentUserId = id
            };

            return View(model);
        }


        [Authorize]
        [HttpPost]
        public ActionResult FriendListDelete(Guid id, FriendListDeleteModel model)
        {
            if(ModelState.IsValid)
            {
                var viewerUser = Repository.AsQueryable<User>().SingleOrDefault(us => us.Id == id);
                if (viewerUser.Id != id) // if current user is not owner of the list then he cant delete friends
                {
                    return RedirectToAction("ProfileView", "Profile", new { id = viewerUser.Id });
                }
                var selectedUsers = Repository.AsQueryable<User>().Where(u => model.UsersSelected.Contains(u.Id));
                foreach (var friend in selectedUsers)
                {
                    
                    // find all relationship with selected friend and deleted it
                    var allRelationship = Repository.AsQueryable<Relationship>().Where(
                        rel =>
                        (rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                        (rel.BaseSubject.Id == viewerUser.Id && rel.BaseSubject2.Id == friend.Id)).ToArray();

                    foreach (var relationship in allRelationship)
                    {
                        Repository.DeleteObject(relationship);
                    }
                }
                Repository.SaveChanges();
                return Json(model);
                //            return RedirectToAction("ProfileView", "Profile", new { id = viewerUser.Id });
            }
            return View(model);
        }

        //search results for friends list
        [Authorize]
        [HttpPost]
        public ActionResult SearchResults(Guid id, string search)
        {
            var viewerUser = CurrentUser;
            var ownerId = id;
            if (id == Guid.Empty) // if its empty then its own friends list
                ownerId = viewerUser.Id;

            var json = Session["allFriends" + ownerId] as string;
            var allFriends = JsonHelper.Deserialize<List<FriendsLookupModels>>(json);

          
            var friends = allFriends.Where(
                usr =>
                usr.FirstName.ToLower().StartsWith(search.ToLower()) ||
                usr.LastName.ToLower().StartsWith(search.ToLower()));
            if (search == "")
            {
                friends = allFriends;
            }

            var addFriend = false; // if true it will show add as a friend button next to the user
            var confirmFriend = false; // if true it will show confirm friendship button next to the user
            var friendsList = new List<Friend>();
            foreach (var friend in friends)
            {
                addFriend = false;
                confirmFriend = false;
                var friendProfilePicturePath = Repository.GetProfilePicturePath(friend.Id);
                addFriend =
                    !Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (((rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) ||
                         (rel.BaseSubject2.Id == friend.Id && rel.BaseSubject.Id == viewerUser.Id)) &&
                        rel.RelationType == RelationshipType.FriendOf)); // try to find if there is any of relationship with current user if so then we will not show button addFriend
                if (friend.Id == viewerUser.Id) // if friend is viewer user then we dont show addFriend button
                    addFriend = false;
                confirmFriend =
                    Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        (rel.BaseSubject.Id == friend.Id && rel.BaseSubject2.Id == viewerUser.Id) &&
                        rel.RelationType == RelationshipType.FriendOf &&
                        (rel.Status == RelationshipStatus.Requested || rel.Status == RelationshipStatus.Postponed)); // friend (requested or gotpostopend by) current user then we show confirm friendship button

                var friendModel = new Friend()
                {
                    FullName = friend.Fullname,
                    Id = friend.Id,
                    ProfilePicturePath = friendProfilePicturePath,
                    AddFriend = addFriend,
                    ConfirmFriend = confirmFriend
                };
                friendsList.Add(friendModel);
            }

            return PartialView("FriendsListTable", friendsList);
        }

        public ActionResult FamilyList(Guid id)
        {
            var viewerUser = CurrentUser;
            User ownerUser = id == Guid.Empty ? viewerUser : Repository.AsQueryable<User>().SingleOrDefault(us => us.Id == id);
            var allFamilyRelationships = GetAllFamilyRelationships(ownerUser);

            var model = new FamilyListModel()
            {
                AllRelationshipChild = allFamilyRelationships["Childrens"].ToArray(),
                AllRelationshipParent = allFamilyRelationships["Parents"].ToArray(),
                AllRelationshipSibling = allFamilyRelationships["Siblings"].ToArray(),
                AllRelationshipCousin = allFamilyRelationships["Cousins"].ToArray(),
                AllRelationshipGrandchild = allFamilyRelationships["Grandchildrens"].ToArray(),
                AllRelationshipGrandparent = allFamilyRelationships["Grandparents"].ToArray(),
                AllRelationshipNephewNiece = allFamilyRelationships["Nephews/Nieces"].ToArray(),
                AllRelationshipUncleAunt = allFamilyRelationships["Uncles/Aunts"].ToArray()
            };
            return View(model);
        }

        #region Postponed, Blocked, Requested List

        [Authorize]
        public ActionResult PostponedList()
        {
            var user = CurrentUser;
            string userId = user.Id.ToString();
            var allPostoponedRelationships = GetSpecialRelationship(user, RelationshipStatus.Postponed);
            var postponedList = new List<PostponedUser>();
            foreach (var postoponedRelationship in allPostoponedRelationships)
            {
                //for family relationship user who requested is the one which have same id as relationship name
                if ((postoponedRelationship.RelationType == RelationshipType.ChildOf ||
                       postoponedRelationship.RelationType == RelationshipType.CousinOf ||
                       postoponedRelationship.RelationType == RelationshipType.GrandchildOf ||
                       postoponedRelationship.RelationType == RelationshipType.SiblingchildOf ||
                       postoponedRelationship.RelationType == RelationshipType.SiblingOf) && postoponedRelationship.Name == userId)
                {
                    continue;
                }

                var id = postoponedRelationship.BaseSubject.Id;
                var name = postoponedRelationship.BaseSubject.FullName;
                
                var baseSubject = postoponedRelationship.BaseSubject;
                if(postoponedRelationship.BaseSubject.Id == user.Id) //if its same as current user id then we take other id
                {
                    id = postoponedRelationship.BaseSubject2.Id;
                    name = postoponedRelationship.BaseSubject2.FullName;
                    baseSubject = postoponedRelationship.BaseSubject2;
                }
                var type = baseSubject.Type == SubjectType.User ? "friend" : "join";

                //if not friend relationship type
                if(type == "friend" && postoponedRelationship.RelationType != RelationshipType.FriendOf)
                {
                    type = GetLoveRelationTypeName(postoponedRelationship).ToLower();
                }
                var newPostpone = new PostponedUser
                                      {
                                          Id = id,
                                          Name = name,
                                          Type = type,
                                          RelationshipId = postoponedRelationship.Id,
                                          BaseSubjectType = baseSubject.Type,
                                          RelationshipType = postoponedRelationship.RelationType
                                      };
                postponedList.Add(newPostpone);
            }
            var model = new PostponedListModel()
                            {
                                CurrentUserId = user.Id,
                                Users = postponedList.ToArray()
                            };

            return View(model);
        }

        [Authorize]
        public ActionResult RequestedList()
        {
            var user = CurrentUser;

            string userId = user.Id.ToString();

            //depending on second parameter gets you all relationships of that type from that user
            var allRequstedRelationships = GetSpecialRelationship(user, RelationshipStatus.Requested);

            var requstedList = new List<PostponedUser>();
            foreach (var requestedRelationship in allRequstedRelationships)
            {
                //for family relationship user who requested is the one which have same id as relationship name
                if ((requestedRelationship.RelationType == RelationshipType.ChildOf ||
                       requestedRelationship.RelationType == RelationshipType.CousinOf ||
                       requestedRelationship.RelationType == RelationshipType.GrandchildOf ||
                       requestedRelationship.RelationType == RelationshipType.SiblingchildOf ||
                       requestedRelationship.RelationType == RelationshipType.SiblingOf) && requestedRelationship.Name == userId)
                {
                    continue;
                }

                var id = requestedRelationship.BaseSubject.Id;
                var name = requestedRelationship.BaseSubject.FullName;


                var baseSubject = requestedRelationship.BaseSubject;
                if (requestedRelationship.BaseSubject.Id == user.Id) //if its same as current user id then we take other id
                {
                    id = requestedRelationship.BaseSubject2.Id;
                    name = requestedRelationship.BaseSubject2.FullName;
                    baseSubject = requestedRelationship.BaseSubject2;
                }
                var type = baseSubject.Type == SubjectType.User ? "friend" : "join";
                //if not friend relationship type
                if (type == "friend" && requestedRelationship.RelationType != RelationshipType.FriendOf)
                {
                    type = GetLoveRelationTypeName(requestedRelationship).ToLower();
                }
                var newPostpone = new PostponedUser
                {
                    Id = id,
                    Name = name,
                    Type = type,
                    RelationshipId = requestedRelationship.Id,
                    BaseSubjectType = baseSubject.Type,
                    RelationshipType = requestedRelationship.RelationType
                };
                requstedList.Add(newPostpone);
            }
            var isAjaxRequest = Request.IsAjaxRequest() ? true : false;

            var model = new PostponedListModel()
            {
                CurrentUserId = user.Id,
                Users = requstedList.ToArray(),
                IsAjaxRequest = isAjaxRequest
            };

            return View(model);
        }

        [Authorize]
        public ActionResult BlockedList()
        {
            var user = CurrentUser;
            string userId = user.Id.ToString();
            var allBlockedRelationships = GetSpecialRelationship(user, RelationshipStatus.Blocked);
            var blockedList = new List<PostponedUser>();
            foreach (var blockedRelationship in allBlockedRelationships)
            {
                //for family relationship user who requested is the one which have same id as relationship name
                if ((blockedRelationship.RelationType == RelationshipType.ChildOf ||
                       blockedRelationship.RelationType == RelationshipType.CousinOf ||
                       blockedRelationship.RelationType == RelationshipType.GrandchildOf ||
                       blockedRelationship.RelationType == RelationshipType.SiblingchildOf ||
                       blockedRelationship.RelationType == RelationshipType.SiblingOf) && blockedRelationship.Name == userId)
                {
                    continue;
                }

                var id = blockedRelationship.BaseSubject.Id;
                var name = blockedRelationship.BaseSubject.FullName;

                var baseSubject = blockedRelationship.BaseSubject;
                if (blockedRelationship.BaseSubject.Id == user.Id) //if its same as current user id then we take other id
                {
                    id = blockedRelationship.BaseSubject2.Id;
                    name = blockedRelationship.BaseSubject2.FullName;
                    baseSubject = blockedRelationship.BaseSubject2;
                }
                var type = baseSubject.Type == SubjectType.User ? "friend" : "join";
                //if not friend relationship type
                if (type == "friend" && blockedRelationship.RelationType != RelationshipType.FriendOf)
                {
                    type = GetLoveRelationTypeName(blockedRelationship).ToLower();
                }
                var newPostpone = new PostponedUser
                {
                    Id = id,
                    Name = name,
                    Type = type,
                    RelationshipId = blockedRelationship.Id,
                    BaseSubjectType = baseSubject.Type,
                    RelationshipType = blockedRelationship.RelationType
                };
                blockedList.Add(newPostpone);
            }
            var model = new PostponedListModel()
            {
                CurrentUserId = user.Id,
                Users = blockedList.ToArray()
            };

            return View(model);
        }

        #endregion

        #region Email sending
        public bool SendEmailConfirmRelationship(Relationship rel)
        {
            var relationshipType = GetLoveRelationTypeName(rel);
            var user = CurrentUser;
            var viewData = new
            {
                XSettings.SiteName,
                BaseSubject = rel.BaseSubject.FullName,
                BaseSubject2 = rel.BaseSubject2.FullName,
                YourName = user.FullName,
                RelationshipId = rel.Id,
                RelationshipType = relationshipType,
                ConfirmFriendshipUrl =
                    new Uri(HttpContext.Request.Url,
                            Url.Action("ConfirmRelationship", "Profile", new { id = rel.Id })).ToString(),
                PostponeFriendshipUrl =
                    new Uri(HttpContext.Request.Url,
                            Url.Action("PostponeRelationship", "Profile", new { id = rel.Id })).ToString(),
                YourProfileUrl =
                           new Uri(HttpContext.Request.Url,
                                   Url.Action("ProfileView", "Profile", new { id = user.Id })).ToString(),
                XSettings.SiteUrl
            };
            var viewDictionary = viewData.ToViewDataDictionary();
            var email = "";
            if (rel.BaseSubject.Id == user.Id)
            {
                return SendTemplatedEmail(new List<string> { ((User)rel.BaseSubject2).Email }, String.Format("{0} site: Relationship confirmation is required", XSettings.SiteName),
                                                   "~/Views/Email/ConfirmRelationshipRequest.cshtml", viewDictionary);
            }
            else
            {
                return SendTemplatedEmail(new List<string> { ((User)rel.BaseSubject).Email }, String.Format("{0} site: Relationship confirmation is required", XSettings.SiteName),
                                                   "~/Views/Email/ConfirmRelationshipRequest.cshtml", viewDictionary);
            }
            
        }

        public bool SendEmailNotifyRelationship(Relationship rel)
        {
            var relationshipType = GetLoveRelationTypeName(rel);
            var user = CurrentUser;
            var viewData = new
            {
                XSettings.SiteName,
                YourName = user.FullName,
                RelationshipType = relationshipType,
                YourProfileUrl =
                           new Uri(HttpContext.Request.Url,
                                   Url.Action("ProfileView", "Profile", new { id = user.Id })).ToString(),
                XSettings.SiteUrl
            };
            var viewDictionary = viewData.ToViewDataDictionary();

            return SendTemplatedEmail(new List<string> { ((User)rel.BaseSubject2).Email }, String.Format("{0} site: Relationship confirmation is required", XSettings.SiteName),
                                                   "~/Views/Email/RelationshipLoveNotify.cshtml", viewDictionary);
        }
        #endregion

        #region Extra functions
        public string GetLoveRelationTypeName(Relationship rel)
        {
            var user = CurrentUser;
            if(rel.RelationType == RelationshipType.EngagedWith)
            {
                return "engaged";
            }
            if (rel.RelationType == RelationshipType.InRelationshipWith)
            {
                return "in relationship";
            }
            if (rel.RelationType == RelationshipType.IsDivorced)
            {
                return "divorced";
            }
            if (rel.RelationType == RelationshipType.IsSingle)
            {
                return "single";
            }
            if (rel.RelationType == RelationshipType.IsWidowed)
            {
                return "widowed";
            }
            if (rel.RelationType == RelationshipType.ItsComplicatedWith)
            {
                return "is complicated";
            }
            if (rel.RelationType == RelationshipType.MarriedWith)
            {
                return "married";
            }
            if (rel.RelationType == RelationshipType.OpenRelationshipWith)
            {
                return "open relationship";
            }
            if(rel.RelationType == RelationshipType.ChildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Parent";
            }
            if (rel.RelationType == RelationshipType.ChildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Child";
            }
            if (rel.RelationType == RelationshipType.GrandchildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Grand parent";
            }
            if (rel.RelationType == RelationshipType.GrandchildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Grand child";
            }
            if (rel.RelationType == RelationshipType.SiblingchildOf && rel.BaseSubject.Id == user.Id)
            {
                return "Uncle/Aunt";
            }
            if (rel.RelationType == RelationshipType.SiblingchildOf && rel.BaseSubject2.Id == user.Id)
            {
                return "Nephew/Niece";
            }
            if (rel.RelationType == RelationshipType.SiblingOf)
            {
                return "Sibling";
            }
            if (rel.RelationType == RelationshipType.CousinOf)
            {
                return "Cousin";
            }
            if (rel.RelationType == RelationshipType.FriendOf)
            {
                return "Friend";
            }
            return "";
        }

        public bool IsLoveRelationship(Relationship rel)
        {
            if(rel.RelationType == RelationshipType.EngagedWith ||
                rel.RelationType == RelationshipType.InRelationshipWith ||
                rel.RelationType == RelationshipType.IsDivorced ||
                rel.RelationType == RelationshipType.IsSingle ||
                rel.RelationType == RelationshipType.IsWidowed ||
                rel.RelationType == RelationshipType.ItsComplicatedWith ||
                rel.RelationType == RelationshipType.MarriedWith ||
                rel.RelationType == RelationshipType.OpenRelationshipWith)
            {
                return true;
            }
            return false;
        }

        public List<Relationship> GetSpecialRelationship(User currentUser, short relationshipStatus)
        {
            //for event,group, page user must be in first row
            //for love relationship and friendship request user must be in second row, cause only user who requested are in first row
            //for family relationship current user can be both rows BaseSubjec & BaseSubject2 but to seek a user who requested we look in relationship name which we do later
            if(relationshipStatus == RelationshipStatus.Requested)
            {
                var allRequstedRelationships =
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    ((rel.BaseSubject.Id == currentUser.Id && rel.BaseSubject2.Type != SubjectType.User) ||
                     (rel.BaseSubject2.Id == currentUser.Id && rel.BaseSubject2.Type == SubjectType.User &&
                      (rel.RelationType == RelationshipType.EngagedWith ||
                       rel.RelationType == RelationshipType.InRelationshipWith ||
                       rel.RelationType == RelationshipType.ItsComplicatedWith ||
                       rel.RelationType == RelationshipType.MarriedWith ||
                       rel.RelationType == RelationshipType.FriendOf ||
                       rel.RelationType == RelationshipType.OpenRelationshipWith)) ||
                     ((rel.BaseSubject.Id == currentUser.Id || rel.BaseSubject2.Id == currentUser.Id) &&
                      (rel.RelationType == RelationshipType.ChildOf ||
                       rel.RelationType == RelationshipType.CousinOf ||
                       rel.RelationType == RelationshipType.GrandchildOf ||
                       rel.RelationType == RelationshipType.SiblingchildOf ||
                       rel.RelationType == RelationshipType.SiblingOf)))
                    && rel.Status == RelationshipStatus.Requested);
                return allRequstedRelationships.ToList();
            }
            if (relationshipStatus == RelationshipStatus.Postponed)
            {
                var allRequstedRelationships =
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    ((rel.BaseSubject.Id == currentUser.Id && rel.BaseSubject2.Type != SubjectType.User) ||
                     (rel.BaseSubject2.Id == currentUser.Id && rel.BaseSubject2.Type == SubjectType.User &&
                      (rel.RelationType == RelationshipType.EngagedWith ||
                       rel.RelationType == RelationshipType.InRelationshipWith ||
                       rel.RelationType == RelationshipType.ItsComplicatedWith ||
                       rel.RelationType == RelationshipType.MarriedWith ||
                       rel.RelationType == RelationshipType.FriendOf ||
                       rel.RelationType == RelationshipType.OpenRelationshipWith)) ||
                     ((rel.BaseSubject.Id == currentUser.Id || rel.BaseSubject2.Id == currentUser.Id) &&
                      (rel.RelationType == RelationshipType.ChildOf ||
                       rel.RelationType == RelationshipType.CousinOf ||
                       rel.RelationType == RelationshipType.GrandchildOf ||
                       rel.RelationType == RelationshipType.SiblingchildOf ||
                       rel.RelationType == RelationshipType.SiblingOf)))
                    && rel.Status == RelationshipStatus.Postponed);
                return allRequstedRelationships.ToList();
            }
            if (relationshipStatus == RelationshipStatus.Blocked)
            {
                var allRequstedRelationships =
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    ((rel.BaseSubject.Id == currentUser.Id && rel.BaseSubject2.Type != SubjectType.User) ||
                     (rel.BaseSubject.Id == currentUser.Id && rel.BaseSubject2.Type == SubjectType.User &&
                      (rel.RelationType == RelationshipType.EngagedWith ||
                       rel.RelationType == RelationshipType.InRelationshipWith ||
                       rel.RelationType == RelationshipType.ItsComplicatedWith ||
                       rel.RelationType == RelationshipType.MarriedWith ||
                       rel.RelationType == RelationshipType.FriendOf ||
                       rel.RelationType == RelationshipType.OpenRelationshipWith)) ||
                     ((rel.BaseSubject.Id == currentUser.Id || rel.BaseSubject2.Id == currentUser.Id) &&
                      (rel.RelationType == RelationshipType.ChildOf ||
                       rel.RelationType == RelationshipType.CousinOf ||
                       rel.RelationType == RelationshipType.GrandchildOf ||
                       rel.RelationType == RelationshipType.SiblingchildOf ||
                       rel.RelationType == RelationshipType.SiblingOf)))
                    && rel.Status == RelationshipStatus.Blocked);
                return allRequstedRelationships.ToList();
            }
            return new List<Relationship>();
        }

        public List<Post> GetAllComments(Post post)
        {
            var allComments = new List<Post>();


            //Only with its comments
            if (post.CommentType == CommentType.PostWithItsComments)
            {
                allComments = post.Children.Where(child => child.PostType == PostType.Comment).OrderBy(com => com.Created).ToList(); // all childrens posts
            }
            //comments from all post with same BaseObject // Global
            else if (post.CommentType == CommentType.PostWithGlobalComments)
            {
                allComments =
                Repository.AsQueryable<Post>().Where(
                    com =>
                    com.BaseObject.Id == post.BaseObject.Id && com.PostType == PostType.Comment &&
                    post.CommentType == CommentType.PostWithGlobalComments).OrderBy(com => com.Created).ToList();
            }

            return allComments;
        }

        public Dictionary<string, List<Friend>> GetAllFamilyRelationships(User ownerUser)
        {

            var allRelationship = // find all relationships that owner is childOf or parentOf or sibling
                Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject.Id == ownerUser.Id &&
                     (rel.RelationType == RelationshipType.ChildOf ||
                      rel.RelationType == RelationshipType.SiblingchildOf ||
                      rel.RelationType == RelationshipType.SiblingOf ||
                      rel.RelationType == RelationshipType.CousinOf ||
                      rel.RelationType == RelationshipType.GrandchildOf) && rel.Status == RelationshipStatus.Confirmed)).Union(Repository.AsQueryable<Relationship>().Where(
                    rel =>
                    (rel.BaseSubject2.Id == ownerUser.Id &&
                     (rel.RelationType == RelationshipType.ChildOf ||
                      rel.RelationType == RelationshipType.SiblingOf ||
                      rel.RelationType == RelationshipType.CousinOf ||
                      rel.RelationType == RelationshipType.SiblingchildOf ||
                      rel.RelationType == RelationshipType.GrandchildOf) && rel.Status == RelationshipStatus.Confirmed)));

            var relationshipListChild = new List<Friend>(); // all childrens
            var relationshipListParent = new List<Friend>(); // all parent
            var relationshipListSibling = new List<Friend>(); // all siblings
            var relationshipListUncleAunt = new List<Friend>(); // all uncles and aunts
            var relationshipListNephewNiece = new List<Friend>(); // all nephews and nieces
            var relationshipListCousin = new List<Friend>(); // all cousin
            var relationshipListGrandparent = new List<Friend>(); // all grandparents
            var relationshipListGrandchild = new List<Friend>(); // all grandchildrens

            var allFamilyRelationships = new Dictionary<string, List<Friend>>();
            allFamilyRelationships.Add("Childrens", relationshipListChild);
            allFamilyRelationships.Add("Parents", relationshipListParent);
            allFamilyRelationships.Add("Siblings", relationshipListSibling);
            allFamilyRelationships.Add("Uncles/Aunts", relationshipListUncleAunt);
            allFamilyRelationships.Add("Nephews/Nieces", relationshipListNephewNiece);
            allFamilyRelationships.Add("Cousins", relationshipListCousin);
            allFamilyRelationships.Add("Grandparents", relationshipListGrandparent);
            allFamilyRelationships.Add("Grandchildrens", relationshipListGrandchild);


            foreach (var relationship in allRelationship)
            {

                var relationshipFullName = relationship.BaseSubject2.FullName;
                var relationshipId = relationship.BaseSubject2.Id;

                // find parents of owner user
                if (relationship.BaseSubject.Id == ownerUser.Id && relationship.RelationType == RelationshipType.ChildOf) // ownerUser is child of baseSubject2 then we take baseSubject2 as a parent of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationship.BaseSubject2.FullName,
                        Id = relationship.BaseSubject2.Id
                    };
                    allFamilyRelationships["Parents"].Add(relationshipModel);
                    //relationshipListParent.Add(relationshipModel);
                }

                //find all childrens of owner user
                else if (relationship.BaseSubject2.Id == ownerUser.Id && relationship.RelationType == RelationshipType.ChildOf) // baseSubject is child of ownerUser then we take baseSubject as children of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationship.BaseSubject.FullName,
                        Id = relationship.BaseSubject.Id
                    };
                    allFamilyRelationships["Childrens"].Add(relationshipModel);
                    //relationshipListChild.Add(relationshipModel);
                }

                //find all nephew and nieces
                else if (relationship.BaseSubject2.Id == ownerUser.Id && relationship.RelationType == RelationshipType.SiblingchildOf) // baseSubject is Siblingchild of  ownerUser then we take baseSubject as nephew/niece of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationship.BaseSubject.FullName,
                        Id = relationship.BaseSubject.Id
                    };
                    allFamilyRelationships["Nephews/Nieces"].Add(relationshipModel);
                    //relationshipListNephewNiece.Add(relationshipModel);
                }

                //find all unlces and aunts
                else if (relationship.BaseSubject.Id == ownerUser.Id && relationship.RelationType == RelationshipType.SiblingchildOf) // ownerUser is Siblingchild of baseSubject2 then we take baseSubject2 as uncle/aunt of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationship.BaseSubject2.FullName,
                        Id = relationship.BaseSubject2.Id
                    };
                    allFamilyRelationships["Uncles/Aunts"].Add(relationshipModel);
                    //relationshipListUncleAunt.Add(relationshipModel);
                }

                //find all cousins
                else if ((relationship.BaseSubject.Id == ownerUser.Id || relationship.BaseSubject2.Id == ownerUser.Id) && relationship.RelationType == RelationshipType.CousinOf) // take that as cousin of ownerUser
                {
                    var relationshipModel = new Friend();
                    if (relationship.BaseSubject.Id == ownerUser.Id)// if ownerUser is BaseSubject then we take fullName from BaseSubject2
                    {
                        relationshipModel.FullName = relationship.BaseSubject2.FullName;
                    }
                    else
                    {
                        relationshipModel.FullName = relationship.BaseSubject.FullName;
                    }
                    if (relationship.BaseSubject.Id == ownerUser.Id)// if ownerUser is BaseSubject then we take id from BaseSubject2
                    {
                        relationshipModel.Id = relationship.BaseSubject2.Id;
                    }
                    else
                    {
                        relationshipModel.Id = relationship.BaseSubject.Id;
                    }
                    allFamilyRelationships["Cousins"].Add(relationshipModel);
                    //relationshipListCousin.Add(relationshipModel);
                }

                //find all grandchilds
                else if (relationship.BaseSubject2.Id == ownerUser.Id && relationship.RelationType == RelationshipType.GrandchildOf) // baseSubject is grandchild of ownerUser then we take baseSubject2 as grandchild of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationship.BaseSubject.FullName,
                        Id = relationship.BaseSubject.Id
                    };
                    allFamilyRelationships["Grandchildrens"].Add(relationshipModel);
                    //relationshipListGrandchild.Add(relationshipModel);
                }

                //find all grandparents
                else if (relationship.BaseSubject.Id == ownerUser.Id && relationship.RelationType == RelationshipType.GrandchildOf) // ownerUser is grandchild of baseSubject2 then we take baseSubject2 as grandparent of ownerUser
                {
                    var relationshipModel = new Friend()
                    {
                        FullName = relationshipFullName,
                        Id = relationshipId
                    };
                    allFamilyRelationships["Grandparents"].Add(relationshipModel);
                    //relationshipListGrandparent.Add(relationshipModel);
                }

                //find all siblings
                else if ((relationship.BaseSubject.Id == ownerUser.Id || relationship.BaseSubject2.Id == ownerUser.Id) && relationship.RelationType == RelationshipType.SiblingOf) // relationship.RelationType == RelationshipType.SiblingOf
                {
                    var relationshipModel = new Friend();
                    if (relationship.BaseSubject.Id == ownerUser.Id)// if ownerUser is BaseSubject then we take fullName from BaseSubject2
                    {
                        relationshipModel.FullName = relationship.BaseSubject2.FullName;
                    }
                    else
                    {
                        relationshipModel.FullName = relationship.BaseSubject.FullName;
                    }
                    if (relationship.BaseSubject.Id == ownerUser.Id)// if ownerUser is BaseSubject then we take id from BaseSubject2
                    {
                        relationshipModel.Id = relationship.BaseSubject2.Id;
                    }
                    else
                    {
                        relationshipModel.Id = relationship.BaseSubject.Id;
                    }
                    allFamilyRelationships["Siblings"].Add(relationshipModel);
                    //relationshipListSibling.Add(relationshipModel);

                }
            }
            return allFamilyRelationships;
        }


        #endregion

        #region Subject members

        public override ActionResult ConfirmRelationshipNotification(Relationship relationship)
        {
            var model = new NotifyModel
            {
                Title = "Relationship request",
                Header = "Confirm relationship request",
                Body = "Relationship request successfully confirmed.",
                NotificationType = NotificationType.Notification
            };

            return RedirectToAction("Notify", "Home", model);
        }

        public override ActionResult PostponeRelationshipNotification(Relationship relationship)
        {
            var model = new NotifyModel
            {
                Title = "Relationship request",
                Header = "Postpone relationship request",
                Body = "Relationship request successfully postponed.",
                NotificationType = NotificationType.Notification
            };

            return RedirectToAction("Notify", "Home", model);
        }

        public override ActionResult PostponeFailedRelationshipNotification(Relationship relationship)
        {
            var model = new NotifyModel
            {
                Title = "Relationship request",
                Header = "Postpone relationship request",
                Body =
                    "Relationship request couldn't be postponed, because the relationship was already confrirmed.",
                NotificationType = NotificationType.Notification
            };

            return RedirectToAction("Notify", "Home", model);
        }
        #endregion
    }
}
